package MovieGuessingGame;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import org.apache.commons.codec.binary.Base64;

import MovieGuessingGame.Database.PlayerDB;
import MovieGuessingGame.Database.PlayerRecord;

/**
 * * The class for the helper threads in this multi threaded server *
 * application. A Player is identified by a character mark * which is either 'X'
 * or 'O'. For communication with the * client the player has a socket with its
 * input and output * streams. Since only text is being communicated we use a *
 * reader and a writer.
 */
public class Player extends Thread {
	/**
	 * 
	 */

	private PlayerRecord record;
	private BaseServer baseServer;
	char mark;
	Player opponent;
	Socket socket;
	BufferedReader input;
	PrintWriter output;
//	InputStream inStream = null;
	byte[] hash = null;
	boolean hasWinner = false;
	boolean playing = false;
	
	/**
	 * * Constructs a handler thread for a given socket and mark * initializes
	 * the stream fields, displays the first two * welcoming messages.
	 */

	public Player(Socket socket) {
		System.out.println("Player()");
		//this.baseServer = baseServer;
		this.socket = socket;
		//this.mark = mark;
		try {
			
			
			input = new BufferedReader( new InputStreamReader( socket.getInputStream() ) );
			output = new PrintWriter(socket.getOutputStream(), true);
			
			String str_hash = input.readLine();
			System.out.println("Player hash: " + str_hash);
			hash = Base64.decodeBase64(str_hash);
			record = new PlayerDB().selectPlayerRecord(hash);
			
			System.out.println("Player found " + record.toString());
			
	
			if (record == null){
				System.out.println("unauthorized player - killing thread");
				//this.destroy();
			}
			

			//output.println("MESSAGE Waiting for opponent to connect");
		} catch (IOException e) {
			System.out.println("Player died: " + e);
		}
		
		System.out.println("our final hash value is "+ new String(Base64.encodeBase64(hash)));
	}
	
	public String getPlayerName() {
		return record.getName();
	}
	
	public boolean isConnected() {
		return socket.isConnected();
	}
	
	public void closeSocket() {
		if (socket.isConnected()) {
			try {
				socket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	public String getRequestedOpponent() throws IOException{
		String result = null;
		
		result =  input.readLine();

			
		return result;
	}

	public void setupGame(BaseServer baseServer, char mark, String movie){
		this.baseServer = baseServer;
		this.mark = mark;
		
		output.println(movie);
		output.println(record.getName());
		output.println(record.getScore());
		output.println(record.getTotalWins());
		
		output.println("WELCOME " + mark);
	}
	/**
	 * * Accepts notification of who the opponent is.
	 * */
	public void setOpponent(Player opponent) {
		this.opponent = opponent;
	}
	
	public void sendGameStart() {
		output.println("GAME_START");
	}

	/** * Handles the otherPlayerMoved message. */
	public void otherPlayerMoved(String selection) {
		System.out.println("otherPlayerMoved()");
		if (hasWinner){
			output.println("DEFEAT");
			output.println("");
		}
		else
		{
			if (selection.contains("DEFEAT"))
				output.println(selection);
			else
				output.println("OPPONENT_MOVED " + selection);
		}
		//output.println(this.hasWinner ? "DEFEAT" : "");
		//output.println("OPPONENT_MOVED " + selection);
		//output.println(this.hasWinner ? "DEFEAT" : "");
		
	}

	/** * The run method of this thread. */
	public void run() {
		try {
			playing = true;
			
			// The thread is only started after everyone connects.
			output.println("MESSAGE All players connected");
			// Tell the first player that it is her turn.
			if (mark == '1') {
				output.println("MESSAGE Your move");
			}

			// Repeatedly get commands from the client and process them.
			while (true) {
				System.out.println("run()");

				String command = input.readLine();
				if (command == null){
					System.out.println("command was null???");
					break;
				}
					
				System.out.println("Command is " +command);
				if (command.contains("DEFEAT")){
					System.out.println("DEFEATED");
					String scoreStr = command.substring(6);
					System.out.println(scoreStr);
					Integer score = new Integer(scoreStr);
					
					new PlayerDB().updatePlayerScore(hash,score.intValue());
					System.out.println("Updated score " + score.intValue());
					hasWinner = true;
					this.baseServer.legalMove("DEFEAT", this);
				}
				if (command.contains("SCORE")){
					System.out.println("SCORE");
					
					
				}
				if (command.startsWith("MOVE")) {
					String selection = command.substring(5);
					if (this.baseServer.legalMove(selection, this)) {
						output.println("VALID_MOVE");
						output.println(this.hasWinner ? "VICTORY" : "");
					} else {
						output.println("MESSAGE ?");
						output.println(this.hasWinner ? "VICTORY" : "");
					}
				} 
				else if (command.startsWith("QUIT")) {
				
					break;
				}
			}
		} catch (IOException e) {
			System.out.println("Player died: " + e);
		} finally {
			try {
				if( socket.isConnected() ){
					socket.close();
				}
				synchronized (BaseServer.class) {
					String name = record.getName();
					System.out.println("DEBUG: removing from map: "+name);
					BaseServer.player_list.remove(record.getName());
				}
			} catch (IOException e) {
			}
		}
	}
}